/** Fichier qui implémente une classe de transformation des points de l'espace.
 *
 * Ce fichier contient l'implémentation de la classe Transformation.
 *
 * @file Transformation.cpp
 * @author Johan "Solo" Luisier
 *
 * @date 2009
 */

#include "Transformation.hpp"

using namespace std;

/** Constructeur par défaut.
 *
 * Ce constructeur permet de définir une transformation
 * quelconque. Par défaut on construit bien sûr l'identité.
 *
 * @param[in] rot matrice de rotation.
 * @param[in] trans nouveau point d'origine (définit la translation).
 * @param[in] rapport est le rapport d'homothétie.
 * @param[in] trVersLoc permet de dire si la transformation permet de
 * passer des coordonnées locales aux coordonnées globales (\e false)
 * ou l'inverse (\e true).
 */
Transformation::Transformation( const MatriceSO3& rot, const Coord& trans,
                                const double& rapport, const bool& trVersLoc )
    : Rotation( rot )
    , Translation( trans )
    , Homothetie( rapport )
    , VaVersLocal( trVersLoc )
{}

/** Constructeur de copie, permettant de dupliquer une Transformation.
 *
 * @param[in] tr Transformation à copier.
 */
Transformation::Transformation( const Transformation& tr )
    : Rotation( tr.Rotation ), Translation( tr.Translation ),
      Homothetie( tr.Homothetie ), VaVersLocal( tr.VaVersLocal )
{}

/** Destructeur, libère la mémoure utilisée.
 *
 * Le destructeur n'a rien de spécial à faire.
 */
Transformation::~Transformation()
{}

/** Opérateur d'affectation.
 *
 * Permet d'affecter une transformation. Est utilisé dans les
 * constructeurs des formes ayant recours à une transformation de
 * l'espace.
 *
 * @param[in] tr Transformation à copier.
 *
 * @return une référence sur l'instance courante modifiée.
 */
Transformation& Transformation::operator=( const Transformation& tr )
{
    Rotation    = tr.Rotation;
    Translation = tr.Translation;
    Homothetie  = tr.Homothetie;
    VaVersLocal = tr.VaVersLocal;

    return *this;
}

/** Méthode d'inversion.
 *
 * Permet d'obtenir l'inverse d'une Transformation. La rotation et la
 * translation sont inversées, on inverse également le rapport
 * d'homothétie. Il faut aussi changer la valeur de VaVersLocal.
 *
 * @return nouvelle instance de Transformation, qui permet de revenir
 * à l'indentité.
 */
Transformation Transformation::inverse() const
{
    return Transformation( Rotation.inverse(), - Translation,
                           1. / Homothetie, ! VaVersLocal );
}

ostream& operator<<( ostream& os, const Transformation& tr )
{
    return os << "Rotation : " << endl << tr.Rotation
              << "Translation : " << tr.Translation << endl
              << "Homothétie : " << tr.Homothetie << endl;
}

/** Méthode de transformation des scalaires.
 *
 * Méthode réalisant la transformation d'un scalaire. Pour un scalaire
 * uniquement l'homothétie est importante.
 *
 * @param[in] scalaire valeur que l'on veut transformer.
 *
 * @return la valeur image de @c scalaire par la transformation.
 */
double Transformation::operator()( const double& scalaire ) const
{
    return scalaire * Homothetie;
}

/** Méthode de transformation des points de l'espace.
 *
 * Méthode réalisant la transformation d'un point de l'espace. Ici la
 * valeur de VaVersLocal est importante : elle détermine l'ordre de
 * composition des 3 opérations, qui ne commutent pas entre elles.
 *
 * @param[in] pt point de l'espace dont on veut les nouvelles coordonnées.
 *
 * @return une nouvelle instance de Coord, qui est l'image de @c pt par
 * la Transformation.
 */
Coord Transformation::operator()( const Coord& pt ) const
{
    if ( VaVersLocal )
        return Rotation * ( pt - Translation ) * Homothetie;
    else
        return Rotation * ( pt * Homothetie ) - Translation;
}

/** Méthode de transformation des vecteurs de l'espace.
 *
 * Méthode réalisant la transformation d'un vecteur de l'espace. Ici
 * la valeur de VaVersLocal n'importe pas : l'homothétie et la
 * rotation commutent.
 *
 * @param[in] vec vecteur de l'espace dont on veut les nouvelles
 * coordonnées.
 *
 * @return une nouvelle instance de Vecteur, qui est l'image de \c vec
 * par la Transformation.
 */
Vecteur Transformation::operator()( const Vecteur& vec ) const
{
    return Homothetie * ( Rotation * vec );
}


/** Méthode de transformation des vecteurs unitaires de l'espace.
 *
 * Méthode réalisant la transformation d'un vecteur unitaire de
 * l'espace. Ici la valeur de VaVersLocal n'importe pas : l'homothétie
 * et la rotation commutent.
 *
 * @warning Est-ce que cette méthode ne devrait pas être supprimée?
 *
 * @param[in] vec vecteur de l'espace dont on veut les nouvelles
 * coordonnées.
 *
 * @return une nouvelle instance de Vecteur, qui est l'image de @c vec
 * par la Transformation.
 */
VecteurU Transformation::operator()( const VecteurU& vec ) const
{
    return Homothetie * ( Rotation * vec );
}


